"""
Copyright © 2021 Walkline Wang (https://walkline.wang)
Gitee: https://gitee.com/walkline/spaceman
"""
from struct import unpack


class BITMAP(object):
	BITMAP_HEADER_LENGTH = 62

	def __init__(self, header_data:bytes):
		self.is_valid_bmp_file = True

		if len(header_data) != BITMAP.BITMAP_HEADER_LENGTH or not header_data.startswith(b'BM'):
			print('invalid bitmap file')
			self.is_valid_bmp_file = False
			return

		self.file_header = BITMAP.FileHeader(header_data[:14])
		self.info_header = BITMAP.InfoHeader(header_data[14:54])
		self.color_table = BITMAP.ColorTable(header_data[54:])


	class FileHeader(object):
		def __init__(self, header_data:bytes):
			self.type,\
			self.size,\
			self.reserved1,\
			self.reserved2,\
			self.offset_bits = unpack('<2sI2HI', header_data)

		def __str__(self):
			return f'\nfile header:\n- type: {self.type}\n- size: {self.size}\n- offset bits: {self.offset_bits}'


	class InfoHeader(object):
		def __init__(self, header_data:bytes):
			self.size,\
			self.width,\
			self.height,\
			self.planes,\
			self.bit_count,\
			self.compression,\
			self.size_image,\
			self.x_ppm,\
			self.y_ppm,\
			self.color_used,\
			self.color_important = unpack('<3I2H6I', header_data)

		def __str__(self):
			return f'\ninfo header:\n- size: {self.size}\n- width: {self.width}\n- height: {self.height}\n- planes: {self.planes}\n- bit count: {self.bit_count}\n- commpression: {self.compression}\n- size image: {self.size_image}\n- x-ppm: {self.x_ppm}\n- y-ppm: {self.y_ppm}\n- color used: {self.color_used}\n- color important: {self.color_important}'


	class RGBQuad(object):
		def __init__(self, rgb_data:bytes):
			self.blue,\
			self.green,\
			self.red,\
			self.reserved = unpack('<4B', rgb_data)

		def __str__(self):
			return f'\nrgb quad:\n- blue: {self.blue}\n- green: {self.green}\n- red: {self.red}'


	class ColorTable(object):
		def __init__(self, color_data:bytes):
			self.white = BITMAP.RGBQuad(color_data[:4])
			self.black = BITMAP.RGBQuad(color_data[4:])

		def __str__(self):
			return f'\ncolor table white:{str(self.white)}\n\ncolor table black:{str(self.black)}'


if __name__ == '__main__':
	try:
		with open('images/bmp/01.bmp', 'rb') as bmp_file:
			header_data = bmp_file.read(BITMAP.BITMAP_HEADER_LENGTH)
			bitmap = BITMAP(header_data)

			if bitmap.is_valid_bmp_file:
				print(bitmap.file_header)
				print(bitmap.info_header)
				print(bitmap.color_table)
	except Exception as e:
		print(e)
